<template>
    <div class="copper-wrapper">
        <div class="img-box">
            <img v-if="props.url" ref="imageRef" class="fit " :src="props.url" />
        </div>
        <div class="btns">
            <el-button class="btn" @click="cancel">取消 {{ $attrs.aspectRatio }}</el-button>
            <el-button class="btn ok" @click="confirm">确认</el-button>
        </div>
    </div>
</template>
<script setup>
// 引入cropperjs库与相关css
import Cropper from 'cropperjs';
import 'cropperjs/dist/cropper.min.css';
import { watch, onMounted, ref } from 'vue';
import { debounce } from 'lodash';
import readBase64FormatFile from '../../util/readBase64FormatFile';

const emits = defineEmits(['clip-img', 'update:show']);
// 传来的图片地址
const props = defineProps({
    show: {
        type: Boolean,
        default: false,
    },
    extName: {
        type: String,
        default:''  
    },
    url: {
        type: String,
        default: ''
    },
    // 比例
    aspectRatio: {
        type: Number,
        default: null,
    },
});
const imageRef = ref(null); //img元素
const clipImgRef = ref('');


/**
 * 获取裁剪的base64图片发给父级
 * @param {canvas} cvs canvas数据
 */
const clipImgEmitBase64Img = (cvs) => {
    // 将canvas转为图片数据 → 参数1:图片格式[image/webp, image/jpeg, image/png] | 参数2：图片裁剪后的清晰度，相当于压缩图片 0 - 1(只对jpeg与webp有效)
    const base64 = cvs.toDataURL(`image/${props.extName}`, 0.75);

    clipImgRef.value = base64;
};

let cropper = null;
onMounted(() => {
    cropper = new Cropper(imageRef.value, {
        aspectRatio: props.aspectRatio, //裁剪比例 → [1 / 1, 19 / 9 ,...........]
        viewMode: 1, //裁剪模式 [0,1,2,3]
        dragMode: 'move',
        // 重点：加载完成将第一次裁剪的图片数据发给父级
        ready() {
            clipImgEmitBase64Img(this.cropper.getCroppedCanvas());
        },
        // 鼠标、手指移开触发
        cropend() {
            clipImgEmitBase64Img(this.cropper.getCroppedCanvas());
        },
        // 缩放触发，这里最好用防抖函数，不然缩放非常卡，影响用户体验，加入我已有防抖，例子如下
        zoom: debounce(function () {
          clipImgEmitBase64Img(this.cropper.getCroppedCanvas());
        }, 500),

        zoom() {
            clipImgEmitBase64Img(this.cropper.getCroppedCanvas());
        },
        // 缩放触发
        zoom() {
            clipImgEmitBase64Img(this.cropper.getCroppedCanvas());
        },
    });
});

// 监听props
watch(props, (val) => {
    // 设置cropper
    if (val.aspectRatio && val.url && cropper) {
        cropper.setAspectRatio(val.aspectRatio);
        cropper.replace(val.url);
    }
});

const cancel = () =>{
    emits('update:show', false);
    emits('clip-img', null);
}
const confirm = () =>{
    emits('update:show', false);
    // base64 to file
    const file = readBase64FormatFile(clipImgRef.value, `image.${props.extName}`);
    emits('clip-img', file);
}

</script>

<style scoped lang="less">
.copper-wrapper {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 101;
    width: 100vw;
    height: 100vh;

    .img-box {
        object-fit: contain;
        max-width: 100%;
        width: 100%;
        height: calc(100% - 74px);
    }
    .btns {
        background-color: #fff;
        text-align: center;
        padding: 20px 0;
        .ok {
            background-color: var(--system-primary-color);
            color: #fff;
            border-color: var(--system-primary-color);
        }
    }
}
</style>
